import * as Cesium from 'cesium'

// 坐标转换工具(屏幕坐标  ---  世界坐标(笛卡尔)  ---  角度值经纬度坐标)
class PositionHandler {
    /**
     * 将弧度制的经纬度转换为笛卡尔坐标
     * @param {Cesium.Viewer} viewer - viewer
     */
    constructor(viewer){
        this.viewer=viewer
    }

    /**
     * 将角度制的经纬度转换为笛卡尔坐标
     * @param {{lng,lat,height}} position - 角度制的经纬度坐标
     * @returns {Cesium.Cartesian3} 返回笛卡尔坐标
     */
    LngToCartesian3Degree(position){
        const {lng,lat,height}=position
        // 如果是角度制的，直接转
        return new Cesium.Cartesian3.fromDegrees(lng,lat,height)
    }

    /**
     * 将弧度制的经纬度转换为笛卡尔坐标
     * @param {Cesium.Cartographic} cartoGraphic - 弧度制的经纬度坐标
     * @returns {Cesium.Cartesian3} 返回笛卡尔坐标
     */
    LngToCartesian3Radian(cartoGraphic){
        // 拿到当前椭球的参考系
        const ellipsoid=this.viewer.scene.globe.ellipsoid
        return ellipsoid.cartographicToCartesian(cartoGraphic)
    }

    /**
     * 将笛卡尔转角度制经纬度
     * @param {Cesium.Cartesian3} position - 弧度制的经纬度坐标
     * @returns {{lng,lat,height}} 返回经纬度
     */
    CartesianToDegree(position){
        const ellipsoid=this.viewer.scene.globe.ellipsoid
        const cartoGraphic=ellipsoid.cartesianToCartographic(position)
        const lng=Cesium.Math.toDegrees(cartoGraphic.longitude)
        const lat=Cesium.Math.toDegrees(cartoGraphic.latitude)
        return {
            lng,lat,height:cartoGraphic.height
        }
    }

    /**
     * 将角度制经纬度(批量)转批量笛卡尔
     * @param {{lng,lat,height}[]} positions - 经纬度坐标数组
     * @returns {Cesium.Cartesian3[]} 返回笛卡尔数组
     */
    LngsToCartesians(positions){
        const flattenPosition=[]
        positions.forEach(position=>{
            const {lng,lat,height}=position
            flattenPosition.push(lng,lat,height)
        })
        return new Cesium.Cartesian3.fromDegreesArrayHeights(flattenPosition)
    }

    /**
     * 将屏幕转世界坐标
     * @param {Cesium.Cartesian2} position - 屏幕坐标
     * @returns {Cesium.Cartesian3} 返回笛卡尔
     */
    ScreenToCartesian(position){
        const ray=this.viewer.camera.getPickRay(position)
        // cesium默认支持射线法，将屏幕转世界
        return this.viewer.scene.globe.pick(
            ray,this.viewer.scene
        )
    }

    /**
     * 将世界坐标转屏幕
     * @param {Cesium.Cartesian3} position - 世界坐标
     * @returns {Cesium.Cartesian2} 返回屏幕坐标
     */
    CartesianToScreen(position){
        return Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, position);
    }

    // 获取矩形四个点
  getRectFourPoints(positions) {
    let res = positions;
    if (positions.length > 1) {
      let p1 = positions[0];
      let p2 = positions[1];

      let c1 = Cesium.Cartographic.fromCartesian(p1);
      let c2 = Cesium.Cartographic.fromCartesian(p2);
      if (c1.height < 0) c1.height = 0;
      if (c2.height < 0) c2.height = 0;
      let lls = this.getRectanglePointsByTwoPoint(c1, c2);

      // 坐标数组转为指定格式
      let ars = [
        lls[0][0],
        lls[0][1],
        c1.height,
        lls[1][0],
        lls[1][1],
        c1.height,
        lls[2][0],
        lls[2][1],
        c1.height,
        lls[3][0],
        lls[3][1],
        c1.height,
        lls[0][0],
        lls[0][1],
        c1.height,
      ];
      res = Cesium.Cartesian3.fromDegreesArrayHeights(ars);
    }
    return res;
  }

  //   获取矩形四个点
  getRectanglePointsByTwoPoint(c1, c2) {
    //转为经纬度
    let lngLat1 = [
      Cesium.Math.toDegrees(c1.longitude),
      Cesium.Math.toDegrees(c1.latitude),
    ];
    let lngLat2 = [
      Cesium.Math.toDegrees(c2.longitude),
      Cesium.Math.toDegrees(c2.latitude),
    ];

    let lngLat3 = [
      Cesium.Math.toDegrees(c1.longitude),
      Cesium.Math.toDegrees(c2.latitude),
    ];
    let lngLat4 = [
      Cesium.Math.toDegrees(c2.longitude),
      Cesium.Math.toDegrees(c1.latitude),
    ];

    return [lngLat1, lngLat3, lngLat2, lngLat4];
  }

  // 世界坐标转角度值经纬度
  Cartesian3ToLngArr(position){
    const ellipsoid = this.viewer.scene.globe.ellipsoid;
    const cartoGraphic = ellipsoid.cartesianToCartographic(position);
    const lng = Cesium.Math.toDegrees(cartoGraphic.longitude);
    const lat = Cesium.Math.toDegrees(cartoGraphic.latitude);
    return [lng,lat]
  }

}

export default PositionHandler